package charlie.shop.ajax;

import charlie.shop.misc.Common;
import com.charlie.beans.Product;
import com.charlie.sessions.Cart;
import com.charlie.sessions.CartLocal;
import com.charlie.sessions.ProductFacadeLocal;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.ejb.EJB;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;
import org.w3c.dom.Attr;
import org.w3c.dom.Document;
import org.w3c.dom.Element;

/**
 * Cart servlet
 *
 * @author Vitaliy Mostipaka <imprtat@gmail.com>
 */
@WebServlet(name = "CartServlet", urlPatterns = {"/ajax/cart"})
public class CartServlet extends HttpServlet {

    @EJB
    private ProductFacadeLocal product;
    private DocumentBuilderFactory xmlFactory;
    private TransformerFactory transformerFactory;

   
    @Override
    public void init() throws ServletException {
        super.init();
        xmlFactory = DocumentBuilderFactory.newInstance();
        transformerFactory = TransformerFactory.newInstance();
    }

    /**
     *  Create cart and process it
     *
     * @param request servlet request
     * @param response servlet response
     * @throws ServletException if a servlet-specific error occurs
     * @throws IOException if an I/O error occurs
     */
    @Override
    protected void doPost(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        response.setContentType("text/xml;charset=UTF-8");

        DocumentBuilder builder = null;
        try {
            builder = xmlFactory.newDocumentBuilder();
        } catch (ParserConfigurationException ex) {
            Logger.getLogger(CartServlet.class.getName()).log(Level.SEVERE, ex.getMessage(), ex);
        }

        PrintWriter out = response.getWriter();

        Document doc = builder.newDocument();
        Element xmlRoot = doc.createElement("cart");

        HttpSession session = request.getSession(true);
        CartLocal cart = (CartLocal) session.getAttribute("cart");
        try {
            if (cart != null) {
                String action = request.getParameter("action");
                if (action.equals("add")) {
                    int itemId = Common.getParametrInt(request, "itemId", 0);
                    int amount = Common.getParametrInt(request, "amount", -1);
                    cart.addItem(itemId, amount);

                } else if (action.equals("set")) {
                    int itemId = Common.getParametrInt(request, "itemId", 0);
                    int amount = Common.getParametrInt(request, "amount", -1);
                    Logger.getLogger(CartServlet.class.getName()).log(Level.SEVERE, "set amount {0}", amount);
                    cart.setItemAmount(itemId, amount);
                    addItems(doc, xmlRoot, cart);

                } else if (action.equals("items")) {
                    addItems(doc, xmlRoot, cart);
                }
                addSummary(doc, xmlRoot, cart);
            }

            doc.appendChild(xmlRoot);
            DOMSource dom = new DOMSource(doc);
            Transformer transformer = transformerFactory.newTransformer();
            StreamResult result = new StreamResult(out);
            transformer.transform(dom, result);

        } catch (Exception ex) {
            Logger.getLogger(CartServlet.class.getName()).log(Level.SEVERE, ex.getMessage(), ex);
        } finally {
            out.close();
        }
    }

    private void addXMLAttr(Document doc, Element el, String name, String value) {
        Attr attr = doc.createAttribute(name);
        attr.setValue(value);
        el.setAttributeNode(attr);
    }

    /**
     * add summary description
     * @param doc
     * @param root
     * @param cart 
     */
    private void addSummary(Document doc, Element root, CartLocal cart) {
        Element total = doc.createElement("total");

        Element amount = doc.createElement("amount");
        amount.appendChild(doc.createTextNode(Integer.toString(cart.getItemsAmount())));
        total.appendChild(amount);

        Element cost = doc.createElement("cost");
        cost.appendChild(doc.createTextNode(Integer.toString(cart.getCost())));
        total.appendChild(cost);

        root.appendChild(total);
    }

    /**
     * add item to the cart
     * @param doc
     * @param root
     * @param cart 
     */
    private void addItems(Document doc, Element root, CartLocal cart) {
        Element xmlItems = doc.createElement("items");
        root.appendChild(xmlItems);
        for (Cart.CartItem item : cart.getItems()) {
            Product prod = product.find(item.getId());
            Element xmlItem = doc.createElement("item");
            addXMLAttr(doc, xmlItem, "id", prod.getProductId().toString());
            addXMLAttr(doc, xmlItem, "name", prod.getName());
            addXMLAttr(doc, xmlItem, "img", prod.getImage());
            addXMLAttr(doc, xmlItem, "cost", Integer.toString(prod.getCost()));
            addXMLAttr(doc, xmlItem, "amount", Integer.toString(item.getAmount()));
            xmlItems.appendChild(xmlItem);
        }
    }
}
